package cn.tedu.lucky.draw.server.job.config;

import cn.tedu.lucky.draw.server.job.listener.CsvToDBListener;
import cn.tedu.lucky.draw.server.job.processor.ActivityProcessor;
import cn.tedu.lucky.draw.server.protocol.po.Activity;
import cn.tedu.lucky.draw.server.repository.ActivityRepository;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.data.RepositoryItemWriter;
import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.PathResource;

import java.io.File;

@Configuration
public class CsvToDBJobConfig {
    /**
     * Job构建工厂
     */
    @Autowired
    private JobBuilderFactory jobBuilderFactory;
    /**
     * Step构建工厂
     */
    @Autowired
    private StepBuilderFactory stepBuilderFactory;

    @Autowired
    private ActivityRepository activityRepository;

    @Bean
    public ItemReader<Activity> itemReader() {
        return new FlatFileItemReaderBuilder<Activity>()
                .name("activityItemReader")//为ItemReader指定示例名称
                .saveState(false)//是否保存状态，不保存状态，如果作业失败重启，它不会从上次失败的位置继续执行
                .resource(new PathResource((new File("doc/activity.csv").getAbsolutePath())))
                .delimited()//以逗号分隔
                .names("name", "description", "img", "status", "sort")
                .targetType(Activity.class) //设置目标类型，即每读取一行数据都会转换为Activity对象
                .linesToSkip(1) //设置在开始读取数据之前要跳过的行数，第一行是标题
                .build();
    }

    @Bean
    public ItemProcessor<Activity, Activity> itemProcessor() {
        return new ActivityProcessor();
    }

    @Bean
    public ItemWriter<Activity> itemWriter() {
        /**
         * RepositoryItemWriter用于将数据保存到数据库中，需要指定Repository，方法名，以及要保存的对象类型。
         */
        RepositoryItemWriter<Activity> activityRepositoryItemWriter = new RepositoryItemWriter<>();
        activityRepositoryItemWriter.setRepository(activityRepository);
        activityRepositoryItemWriter.setMethodName("save");
        return activityRepositoryItemWriter;
    }

    @Bean
    public Step csvToDBStep() {
        return stepBuilderFactory.get("csvToDBStep")
                .<Activity, Activity>chunk(1000) //设置批处理的大小,每次处理的块大小为1000
                .reader(itemReader())
                .processor(itemProcessor())
                .writer(itemWriter())
                .build();
    }

    @Bean
    public CsvToDBListener listener() {
        return new CsvToDBListener();
    }

    @Bean
    public Job csvToDBJob() {
        return jobBuilderFactory.get("csvToDBJob")
                .start(csvToDBStep()) //设置Job的第一步为csvToDBStep
                .incrementer(new RunIdIncrementer())//设置Job的运行标识，每次运行Job时，标识会自动加1,可以保证Job的唯一性，以此实现重复执行Job的效果。
                .listener(listener())//设置Job的监听器，用于监听Job的执行情况
                .build();
    }

}
